/**
 * @file Graphics.hpp
 *
 * @date 25/12/2011
 * @author Tales 
 *
 */

#ifndef GRAPHICS_HPP_
#define GRAPHICS_HPP_

#include <SDL.h>
#include <utility>

namespace yep
{
using namespace std;
class Color;


/**
 * @brief Classe que executa operações em uma surface
 */
class Graphics
{
public:
	/**
	 * @brief Construtor
	 * @param surface_ a superfície
	 * @param own se verdadeiro, apaga a superfície do Destrutor
	 */
	Graphics(SDL_Surface *surface_, bool own = false);

	/**
	 * @brief Destrutor
	 */
	~Graphics();

	/**
	 * @brief Obtém um pixel.
	 * @return a cor do pixel
	 */
	Uint32 getPixelRaw(Sint16 x, Sint16 y);

	/**
	 * @brief Obtém um pixel.
	 * @return a cor do pixel
	 */
	Color getPixel(Sint16 x, Sint16 y);

	/**
	 * @brief Desenha um pixel
	 * @param pos a posição
	 */
	void drawPixel(const pair<int, int> &pos);

	/**
	 * @brief Desenha uma linha
	 * @param p1 posição inicial.
	 * @param p2 posição final.
	 */
	void drawLine(const pair<int, int> &p1, const pair<int, int> & p2);

	/**
	 * @brief Desenha um retângulo "vazado"
	 * @param p1 posição inicial.
	 * @param p2 posição final.
	 */
	void drawRectangle(const pair<int, int> &p1, const pair<int, int> & p2);

	/**
	 * @brief Desenha um retângulo preenchido
	 * @param p1 posição inicial.
	 * @param p2 posição final.
	 */
	void fillRectangle(const pair<int, int> &p1, const pair<int, int> & p2);

	/**
	 * @brief Desenha uma elípse "vazada"
	 * @param p1 posição inicial.
	 * @param p2 posição final.
	 */
	void drawEllipsis(const pair<int, int> &p1, const pair<int, int> & p2);

	/**
	 * @brief Desenha uma elípse preenchida.
	 * @param p1 posição inicial.
	 * @param p2 posição final.
	 */
	void fillEllipsis(const pair<int, int> &p1, const pair<int, int> & p2);

	/**
	 * @brief Blita deste gráfico em outro
	 * @param dst destino.
	 * @param position poição onde desenhar (no destino)
	 */
	void blit(const Graphics &src, const pair<int, int> &position);

	/**
	 * @brief Blita uma parte deste gráfico em outro
	 * @param dst destino
	 * @param position posição
	 * @param slice Pedaço
	 */
	void blit(const Graphics &src, const pair<int, int> &position, SDL_Rect slice);

	/**
	 * @brief Cria uma nova superfíce e copia os pixels da atual para esta nova
	 * @return uma superfície. A função delega a responsabilidade de deletá-la para o receptor.
	 */
	SDL_Surface *clone();

	/**
	 * @brief Cria uma nova superfíce e copia os pixels da área selecionada para esta nova
	 * @param slice a area selecionada
	 * @return uma superfície. A função delega a responsabilidade de deletá-la para o receptor.
	 */
	SDL_Surface *clone(SDL_Rect slice);

	/**
	 * @brief Pinta uma área contígua.
	 * @param pos a posição inicial.
	 */
	void floodFill(const pair<int, int> &pos);

	/**
	 * @brief Obtém a cor atual em formato universal
	 */
	Color getColor();

	/**
	 * @brief Altera a cor atual (formato universal)
	 */
	void setColor(const Color &color);

	/**
	 * @brief Obtém a cor atual em formato específico da superfície
	 */
	Uint32 getRawColor() const;

	/**
	 * @brief Altera a cor atual (formato específico da superfície)
	 */
	void setRawColor(Uint32 rawColor);

	/**
	 * @brief Obtém a superfície atual
	 * @return a superfície. A posse desta não é repassada, então @b não libere sua memória.
	 */
	SDL_Surface *getSurface() const;

	/**
	 * @brief Altera a superfície atual
	 * @param surface a superfície
	 * @param own Verdadeiro se a gráfico deve liberar a memória da superfície quando for destruída
	 */
	void setSurface(SDL_Surface *surface, bool own = false);
private:
	void putPixelRaw(Sint16 x, Sint16 y, Uint32 pixel);
	void putPixel(Sint16 x, Sint16 y);
	void putPixelAlpha(Sint16 x, Sint16 y);
	SDL_Surface *surface;
	Uint32 rawColor;
	bool useAlpha;
};

} /* namespace yep */
#endif /* GRAPHICS_HPP_ */
